home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright © 1991-1995 by TopSoft Inc. All rights reserved.
-
- You may distribute this file under the terms of the TopSoft
- Artistic License, accompanying this package.
-
- This file was developed by George (ty) Tempel in connection with TopSoft, Inc..
- See the Modification History for more details.
-
- Product
- About Box
-
- FILE
- ABox.c
-
- NAME
- ABox.c, part of the ABox project source code,
- responsible for the top level handling of the AboutBox.
-
- DESCRIPTION
- This file contains defines for the about box modules.
-
- DEVELOPED BY
- George (ty) Tempel netromancr@aol.com
- All code in this file, and its associated header file was
- Created by George (ty) Tempel in connection with the TopSoft, Inc.
- "FilterTop" application development, except where noted.
-
- CARETAKER - George (ty) Tempel <netromancr@aol.com>
- Please consult this person for any changes or suggestions to this file.
-
- MODIFICATION HISTORY
-
- dd mmm yy - xxx - patchxx: description of patch
- 10 June 94 - ty - Initial Version Created
- 20-july-94 - ty - initial version released
- 22-july-94 - ty - 1.0.3 - added correct modeless dialog resource,
- corrected code for clicking to foreground
- 25-july-94 - ty - 1.0.4 - corrected code (again) for clicking to
- foreground via title-bar click
- 28-july-94 - ty - 1.0.6 - added and rearranged code to correctly
- deactivate the topic list when moved to
- the background (within the layer or
- across the layers)
- 23-may-95 - ty - changes for compatibility with the CodeWarrior CW6
- release and the associated Universal Headers from Apple:
- most methods that returned references now have "Ref" at
- the end of their methods names to prevent possible collisions
- with datatypes and classes of the same name (older versions
- of the compiler didn't have a problem with this).
-
- */
-
- /*===========================================================================*/
-
- /*======= Segmentation directives ========*/
-
- #ifdef USE_MANUAL_SEGMENTATION
- #pragma segment ty
- #endif
-
- /*============ Header files ==============*/
-
-
- #include "ABox.h"
- #include "ABoxDefs.h"
- #include "ABUEnvDialog.h"
- #include "ABSound.h"
-
- /*=============== Globals ================*/
-
- /*================ CODE ==================*/
-
- /*=============================== ABox::ABox ================================*/
-
- ABox::ABox(void)
- {
- // initialize the properties...
- this->HomeFolderRef() = NULL;
- this->FirstTopicRef() = 1;
- this->FirstSlideRef() = 1;
- this->SplashTimeRef() = kABoxNoSplash;
- this->CallerResFileRef() = ::CurResFile();
- this->UpdaterRef() = NULL;
- this->ModalIndicatorRef() = kABoxModal;
- this->AppNameAndVersionRef() = NULL;
- this->WindowNameRef() = NULL;
- this->DialogIDRef() = kABmodalDialog;
- this->TextFontRef() = kABoxTextFont;
- this->TextSizeRef() = kABoxTextSize;
- this->TextFaceRef() = kABoxTextFace;
- this->ListHandleRef() = NULL;
-
- this->InBackgroundFlagRef() = false;
- this->ReportMemoryFlagRef() = false;
-
- this->UseSoundMgrFlagRef() = this->UseDragMgrFlagRef() = this->UseSpeechMgrFlagRef() = true;
-
- // now for the private elements
- this->TopicsRef() = new ABTopicList;
- this->WindowRef() = NULL;
- this->ThreadsHandlerRef() = NULL;
- this->WindowUpFlagRef() = false;
- this->ModalUPPRef() = NewModalFilterProc (this->ModalEventFilter);
- } // end ABox
-
-
-
-
-
- /*=============================== ABox::~ABox ================================*/
-
- ABox::~ABox(void)
- {
- (void)Close();
-
- if (this->TopicsRef())
- {
- delete this->TopicsRef();
- this->TopicsRef() = NULL;
- }
-
- if (this->UpdaterRef())
- {
- DisposeRoutineDescriptor(this->UpdaterRef());
- this->UpdaterRef() = NULL;
- } // end if block
-
- if (this->ThreadsHandlerRef())
- {
- DisposeRoutineDescriptor(this->ThreadsHandlerRef());
- this->ThreadsHandlerRef() = NULL;
- } // end if block
-
- if (this->HomeFolderRef())
- {
- ::DisposPtr((Ptr)this->HomeFolderRef());
- this->HomeFolderRef() = NULL;
- }
-
- if (this->AppNameAndVersionRef())
- {
- ::DisposPtr((Ptr)this->AppNameAndVersionRef());
- this->AppNameAndVersionRef() = NULL;
- }
-
- if (this->WindowNameRef())
- {
- ::DisposPtr((Ptr)this->WindowNameRef());
- this->WindowNameRef() = NULL;
- }
-
- if (this->ModalUPPRef())
- {
- DisposeRoutineDescriptor (this->ModalUPPRef());
- } // end if block
-
- } // end ~ABox
-
-
-
-
- /*=============================== ABox::Close ================================*/
- OSErr ABox::Close(void)
- {
- OSErr error = noErr;
-
-
- // hold everything!
- error = Stop();
-
- if (this->ListHandleRef())
- {
- ::LDispose(this->ListHandleRef());
- this->ListHandleRef() = NULL;
- }
-
- if (this->WindowRef())
- {
- ::HideWindow(this->WindowRef());
- ::DisposeDialog(this->WindowRef());
- this->WindowRef() = NULL;
- this->WindowUpFlagRef() = false;
- }
-
- return error;
- } // end Close
-
-
-
-
- /*=============================== ABox::GetProperty ================================*/
- OSErr ABox::GetProperty (ABProperty prop, void *ptr, long *ptrSize)
- {
- OSErr error = noErr;
- long pSize;
-
- // begin here...
- //
- if (!ptr)
- return kABPropertyNullStorage;
-
- switch (prop)
- {
- case kABoxUseSpeechMgr:
- *((Boolean *)ptr) = this->UseSpeechMgrFlagRef();
- pSize = kABoxUseSpeechMgrSize;
- break;
- case kABoxUseDragMgr:
- *((Boolean *)ptr) = this->UseDragMgrFlagRef();
- pSize = kABoxUseDragMgrSize;
- break;
- case kABoxUseSoundMgr:
- *((Boolean *)ptr) = this->UseSoundMgrFlagRef();
- pSize = kABoxUseSoundMgrSize;
- break;
- case kABoxIsFinished:
- *((Boolean *)ptr) = !this->WindowRef();
- pSize = kABoxIsFinishedSize;
- break;
- case kABoxInBackground:
- *((Boolean *)ptr) = this->IsInBackground();
- pSize = kABoxInBackgroundSize;
- break;
- case kABoxReportMemory:
- *((Boolean *)ptr) = this->ReportMemoryFlagRef();
- pSize = kABoxReportMemorySize;
- break;
- case kABoxHomeFolder:
- if (this->HomeFolderRef())
- {
- ::BlockMove ((Ptr)this->HomeFolderRef(), ptr, kABoxHomeFolderSize);
- if (ptrSize)
- *ptrSize = kABoxHomeFolderSize;
- } else {
- error = paramErr;
- } // end if block
- break;
- case kABoxSplashTimeSeconds:
- *((ABoxSplashTimeType *)ptr) = this->SplashTimeRef();
- pSize = kABoxSplashTimeSecondsSize;
- break;
- case kABoxNumberOfTopics:
- if (this->TopicsRef())
- *((ABListCount *)ptr) = this->TopicsRef()->Count();
- else
- *((ABIndex *)ptr) = 0;
- pSize = kABoxNumberOfTopicsSize;
- break;
- case kABoxFirstTopicNumber:
- *((ABIndex *)ptr) = this->FirstTopicRef();
- *ptrSize = kABoxFirstTopicNumberSize;
- break;
- case kABoxCurrentTopic:
- if (this->TopicsRef())
- *((ABTopic **)ptr) = (ABTopic *)this->TopicsRef()->GetCurrentLink();
- else
- *((ABTopic **)ptr) = NULL;
- pSize = kABoxCurrentTopicSize;
- break;
- case kABoxFirstSlideNumber:
- *((ABIndex *)ptr) = this->FirstSlideRef();
- pSize = kABoxFirstSlideNumberSize;
- break;
- case kABoxAppResFile:
- *((short *)ptr) = this->CallerResFileRef();
- pSize = kABoxAppResFileSize;
- break;
- case kABoxUpdater:
- *((UpdateWindowUPP *)ptr) = this->UpdaterRef();
- pSize = kABoxUpdaterSize;
- break;
- case kABoxModalIndicator:
- *((ABoxModalIndicator *)ptr) = this->ModalIndicatorRef();
- pSize = kABoxModalIndicatorSize;
- break;
- case kABoxAppNameAndVersion:
- if (ptr && this->AppNameAndVersionRef())
- ::BlockMove ((Ptr)this->AppNameAndVersionRef(),
- (Ptr)ptr,
- kABoxAppNameAndVersionRefSize);
- pSize = kABoxAppNameAndVersionRefSize;
- break;
- case kABoxThreadsHandler:
- *((DoThreadsUPP *)ptr) = this->ThreadsHandlerRef();
- pSize = kABoxThreadsHandlerSize;
- break;
- case kABoxTextFont:
- *((ABoxTextFontType *)ptr) = this->TextFontRef();
- pSize = kABoxTextFontSize;
- break;
- case kABoxTextSize:
- *((ABoxTextSizeType *)ptr) = this->TextSizeRef();
- pSize = kABoxTextSizeSize;
- break;
- case kABoxTextFace:
- *((ABoxTextFaceType *)ptr) = this->TextFaceRef();
- pSize = kABoxTextFaceSize;
- break;
- case kABoxLastEvent:
- *((EventRecord *)ptr) = this->LastEventRef();
- break;
- case kABoxListHandle:
- (*(ListHandle *)ptr) = this->ListHandleRef();
- pSize = kABoxListHandleSize;
- break;
- case kABoxWindowTitle:
- if (!this->WindowNameRef() && this->WindowRef())
- {
- this->WindowNameRef() = (StringPtr)::NewPtrClear(kABoxWindowTitleSize);
- error = ::MemError();
- if (error || !this->WindowNameRef())
- return error;
- if (this->WindowNameRef() == NULL)
- return paramErr;
- ::GetWTitle (this->WindowRef(), this->WindowNameRef());
- } // end if block
-
- if (ptr && this->WindowNameRef())
- ::BlockMove ((Ptr)this->WindowNameRef(),
- (Ptr)ptr,
- kABoxWindowTitleSize);
- pSize = kABoxAppNameAndVersionRefSize;
- break;
- case kABoxWindow:
- *((WindowPtr *)ptr) = this->WindowRef();
- pSize = kABoxWindowSize;
- break;
- default:
- error = kABoxSuperProperty::GetProperty(prop, ptr, ptrSize);
- break;
- } // end switch block
-
- if (ptrSize && !error)
- *ptrSize = pSize;
-
- return error;
-
- } // end GetProperty
-
-
-
-
-
- /*=============================== ABox::SetProperty ================================*/
- OSErr ABox::SetProperty (ABProperty prop, void *ptr, long ptrSize)
- {
- OSErr error = noErr;
- const Boolean resolveAliasChains = true;
- Boolean targetIsFolder = false,
- wasAliased = false;
-
- long pSize;
- // begin here...
- //
- if (!ptr)
- return kABPropertyNullStorage;
-
- switch (prop)
- {
- case kABoxIsFinished:
- case kABoxInBackground:
- case kABoxWindow:
- case kABoxListHandle:
- case kABoxNumberOfTopics:
- case kABoxCurrentTopic:
- error = kABPropertyReadOnly;
- break;
- case kABoxUseSpeechMgr:
- this->UseSpeechMgrFlagRef() = *((Boolean *)ptr);
- pSize = kABoxUseSpeechMgrSize;
- break;
- case kABoxUseDragMgr:
- this->UseDragMgrFlagRef() = *((Boolean *)ptr);
- pSize = kABoxUseDragMgrSize;
- break;
- case kABoxUseSoundMgr:
- this->UseSoundMgrFlagRef() = *((Boolean *)ptr);
- pSize = kABoxUseSoundMgrSize;
- break;
- case kABoxReportMemory:
- this->ReportMemoryFlagRef() = *((Boolean *)ptr);
- break;
- case kABoxHomeFolder:
- FSSpec tFSS;
-
- if (!this->HomeFolderRef())
- {
- this->HomeFolderRef() = (FSSpecPtr)::NewPtrClear(kABoxHomeFolderSize);
- error = ::MemError();
- if (error || !this->HomeFolderRef())
- return error;
-
- } // end if block
-
- ::BlockMove (ptr, (Ptr)&tFSS, kABoxHomeFolderSize);
-
- error = ::ResolveAliasFile (&tFSS,
- resolveAliasChains,
- &targetIsFolder,
- &wasAliased);
- BlockMove ((Ptr)&tFSS, (Ptr)this->HomeFolderRef(), kABoxHomeFolderSize);
- break;
- case kABoxSplashTimeSeconds:
- this->SplashTimeRef() = *((ABoxSplashTimeType *)ptr);
- break;
- case kABoxFirstTopicNumber:
- this->FirstTopicRef() = *((ABIndex *)ptr);
- break;
- case kABoxFirstSlideNumber:
- this->FirstSlideRef() = *((ABIndex *)ptr);
- break;
- case kABoxAppResFile:
- this->CallerResFileRef() = *((short *)ptr);
- break;
- case kABoxUpdater:
- this->UpdaterRef() = *((UpdateWindowUPP *)ptr);
- break;
- case kABoxModalIndicator:
- this->ModalIndicatorRef() = *((ABoxModalIndicator *)ptr);
- break;
- case kABoxAppNameAndVersion:
- if (!this->AppNameAndVersionRef())
- {
- this->AppNameAndVersionRef() = (StringPtr)::NewPtrClear(kABoxAppNameAndVersionRefSize);
- error = ::MemError();
- if (error || !this->AppNameAndVersionRef())
- return error;
- }
- ::BlockMove (ptr, (Ptr)this->AppNameAndVersionRef(), *((StringPtr)ptr) + 1);
- break;
- case kABoxThreadsHandler:
- this->ThreadsHandlerRef() = *((DoThreadsUPP *)ptr);
- break;
- case kABoxTextFont:
- this->TextFontRef() = *((ABoxTextFontType *)ptr);
- break;
- case kABoxTextSize:
- this->TextSizeRef() = *((ABoxTextSizeType *)ptr);
- break;
- case kABoxTextFace:
- this->TextFaceRef() = *((ABoxTextFaceType *)ptr);
- break;
- case kABoxLastEvent:
- this->LastEventRef() = *((EventRecord *)ptr);
- break;
- case kABoxWindowTitle:
- if (!this->WindowNameRef())
- {
- this->WindowNameRef() = (StringPtr)::NewPtrClear(kABoxWindowTitleSize);
- error = MemError();
- if (error || !this->WindowNameRef())
- return error;
- }
- ::BlockMove (ptr, (Ptr)this->WindowNameRef(), *((StringPtr)ptr) + 1);
- if (this->WindowRef())
- ::SetWTitle (this->WindowRef(), this->WindowNameRef());
- break;
- default:
- error = kABoxSuperProperty::SetProperty(prop, ptr, ptrSize);
- break;
- } // end switch block
-
- return error;
-
- } // end SetProperty
-
-
-
-
-
-
-
- /*=============================== ABox::DoThreads ================================*/
- //
- // This internal method will allow other threads some time,
- // if need be.
- //
- OSErr ABox::DoThreads(void)
- {
- // begin here...
-
- // adding support for background processing of filters/superfilters via
- // the thread mechanism.
- //
-
- if (this->ThreadsHandlerRef())
- return CallDoThreadsUpdateProc(this->ThreadsHandlerRef());
- else
- return noErr;
-
- } // end DoThreads
-
-
-
-
-
-
- /*=============================== ABox::Draw ================================*/
- //
- // When envoked, the Draw method will prime the about box and display it
- // for the user. This method will return to the caller, which must then dispatch
- // events to the about box via the caller's event loop processing.
- //
- OSErr ABox::Draw(WindowPtr /*localWindow*/)
- {
- //#pragma unused (localWindow)
-
- OSErr error = noErr;
-
- ABTopic *topic = NULL;
- Boolean handled = false;
- GrafPtr oldPort;
-
- short itemType;
- Handle itemHandle;
- Rect itemRect;
-
- // begin here...
- //
- if (!this->TopicsRef())
- return paramErr;
-
- ::GetPort (&oldPort);
-
- // have we been here before?
- if (this->DoesntHaveWindow())
- {
- // no, so build the about box...
- error = this->BuildABox();
- if (error || this->DoesntHaveWindow())
- {
- // oops! problems building it, so leave!
- ABERR("\pSorry, error from Build A Box");
- return error;
- } // end if block
- } // end if (!this->WindowRef()) block
-
- ::ShowWindow(this->GetWindow());
-
- if (this->HasWindowNameRef())
- ::SetWTitle (this->GetWindow(), this->WindowNameRef());
-
- this->WindowUpFlagRef() = true;
- this->InBackgroundFlagRef() = false;
-
- if (!error)
- {
- // we have a valid about box, so draw it...
- topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
- if (!topic)
- {
- ABERR("\pSorry, no topic from this->TopicsRef() CurrentLink");
- error = paramErr;
- } else {
- ::GetDItem(this->GetWindow(), kAboutBoxSlideField, &itemType, &itemHandle, &itemRect);
- error = topic->ResizeAndDraw(itemRect, this->GetWindow());
-
- } // end if block
- } // end if block
-
- error = this->ChangeControls();
-
- ::SetPort (oldPort);
-
- return error;
-
- } // end Draw
-
-
-
-
-
- /*=============================== ABox::BuildABox ================================*/
- //
- // When envoked, the BuildABox internal method will prime the about box
- // by loading the this->TopicsRef(), creating the list, setting up the default dialog
- // items, etc.
- //
- OSErr ABox::BuildABox (void)
- {
- OSErr error = noErr;
- UserItemUPP theUPP;
- short itemType;
- Handle itemHandle;
- Rect itemRect;
- short fontHeight;
- short adjustment;
- GrafPtr oldPort;
-
- ABUEnvDialog *dialogEnv = NULL;
- ABTopic *topic = NULL;
-
- Cell firstCellToShow;
-
- // begin here...
-
-
- // try and load the dialog box...
- ::GetPort (&oldPort);
- if (this->SplashTimeRef() == kABoxWaitForApplicationSplash)
- this->ModalIndicatorRef() = kABoxMoveableModal;
-
- switch (this->ModalIndicatorRef())
- {
- case kABoxMoveableModal:
- this->DialogIDRef() = kABmoveableModalDialog;
- break;
- case kABoxModeless:
- this->DialogIDRef() = kABmodelessDialog;
- break;
- case kABoxModal:
- default:
- this->DialogIDRef() = kABmodalDialog;
- break;
- } // end switch block
- this->WindowRef() = ::GetNewDialog (this->DialogIDRef(), kABallocateDialogRecordStorage, kABdialogInFront);
- error = ::ResError();
- if (error || this->DoesntHaveWindow())
- {
- // the attempt to load the dialog resource failed.
- ::SetPort (oldPort);
- return error;
- } // end if block
-
- // initialize here...
- ::SetPort (this->GetWindow());
-
- // set up the text stuff...
- //
- ::TextFont(this->TextFontRef());
- ::TextSize(this->TextSizeRef());
- ::TextFace(this->TextFaceRef());
- // set the procedure pointer for the user items in the dialog.
- //
- // Before you display the dialog box, use the SetDialogItem procedure to install
- // this procedure in the dialog record. Before using SetDialogItem, you must first
- // use the GetDialogItem procedure to obtain a handle to an item of type userItem.
- // If you enable the application-defined item that you draw with this procedure,
- // the ModalDialog procedure and the DialogSelect function return the item’s number
- // when the user clicks that item.
- //
- //ABoxDebugNew();
- theUPP = NewUserItemProc(DrawDialogItem);
- ::GetDItem(this->GetWindow(), kAboutBoxSlideField, &itemType, &itemHandle, &itemRect);
- ::SetDItem(this->GetWindow(), kAboutBoxSlideField, itemType, (Handle)theUPP, &itemRect);
-
- ::GetDItem(this->GetWindow(), kAboutBoxTopic, &itemType, &itemHandle, &itemRect);
-
- // calculate the "correct" size for the list based upon the
- // dialog's font characteristics.
- //
- fontHeight = ABUFonts::FindFontHeight();
- //adjustment = (itemRect.bottom - itemRect.top - 2 * kABbezelShades) % fontHeight;
- adjustment = (itemRect.bottom - itemRect.top) % fontHeight;
-
- // give the list a nice interval to work with, allowing the slack to go to or
- // come from the app and version area
- //
- itemRect.bottom += adjustment;
- ::SetDItem(this->GetWindow(), kAboutBoxTopic, itemType, (Handle)theUPP, &itemRect);
-
- // make the modifications to the kAboutBoxAppAndVersion dialog
- // item to compensate for fiddling with the kAboutBoxTopic item.
- //
- ::GetDItem(this->GetWindow(), kAboutBoxAppAndVersion, &itemType, &itemHandle, &itemRect);
- itemRect.top += adjustment;
- ::SetDItem(this->GetWindow(), kAboutBoxAppAndVersion, itemType, (Handle)theUPP, &itemRect);
-
- dialogEnv = new ABUEnvDialog;
- if (dialogEnv)
- {
- if (dialogEnv->IsPresent())
- {
- error = ::SetDialogDefaultItem(this->GetWindow(), kAboutBoxOK);
- error = ::SetDialogCancelItem(this->GetWindow(), kAboutBoxOK);
- error = ::SetDialogTracksCursor(this->GetWindow(), false);
- } // end if block
- delete dialogEnv;
- } // end if block
-
- // push this object into the refCon of the dialog box so we can
- // allow the dialog manager routines access
- //
- ::SetWRefCon(this->GetWindow(), (long) this);
-
- error = this->TopicsRef()->Load(this->HomeFolderRef(), this->CallerResFileRef());
- if (error)
- {
- ABERR("\pSorry, error from this->TopicsRef() Load(this->HomeFolderRef())");
- return error;
- } // end if block
-
- error = this->CreateAndFillTopicList();
- if (error)
- {
- ABERR("\pSorry, error from CreateAndFillTopicList");
- return error;
- } // end if block
-
-
- // select the "first" topic, whichever one that might really be...
- ::SetPt (&firstCellToShow, 0, this->FirstTopicRef() - 1);
- ::LSetSelect (true, firstCellToShow, this->ListHandleRef());
-
- topic = (ABTopic *)this->TopicsRef()->GotoLink (this->FirstTopicRef());
- if (!topic)
- return paramErr;
- else
- error = topic->GotoSlide (this->FirstSlideRef());
-
-
- return error;
- } // end BuildABox
-
-
-
-
-
-
- /*=============================== CreateAndFillTopicList ===============================*/
- //
- // this function will perform the list creation and population.
- //
- // the function returns an OSErr to indicate any errors.
- //
- //
- // is called by:
- // DoAbout
- //
- OSErr ABox::CreateAndFillTopicList (void)
- {
- OSErr error = noErr;
-
- // these items are for the geometry of the List
- short itemType;
- Handle itemHandle;
- Rect itemRect;
-
- // these items are used to build the List
- Rect dataBounds; // the dimensions of the data in the list
- Point cellSize; // width and height of a cells rectangle
- Point cell; // an index through the list
- long numberOfTopics;
- ListClickLoopUPP clickLoopUPP = NULL;
-
- // these items are used in the actual cell construction
- // for the list
- short i, index;
- long topicDepth;
- ABTopic *topic;
-
- // these items are used to determine the pseudo-user
- // name in the list
- StringHandle userName;
- Str255 topicName;
- Str255 youFile,
- temp;
- Boolean sameString = false;
-
-
- // begin..
- //
-
- //-------------------------------
- //
- // now let's create the list to hold the various this->TopicsRef().
- //
- ::GetDItem(this->GetWindow(), kAboutBoxTopic, &itemType, &itemHandle, &itemRect);
-
- // make room for topic list's scroll bars (see IM IV-270)
- this->DrawFrame (itemRect);
- itemRect.right -= kABscrollBarWidth;
-
- // create a list
- //
- numberOfTopics = this->TopicsRef()->Count();
- ::SetRect (&dataBounds, 0, 0, 1, (short)numberOfTopics);
-
- // let the list manager determine the best size
- ::SetPt (&cellSize, 0, 0);
-
- // create the list
- //ABoxDebugNew();
- this->ListHandleRef() = ::LNew(&itemRect, // view rectangle
- &dataBounds, // dimensions of the list
- cellSize, // size of the cells
- 0, // procID to use
- this->GetWindow(), // containing window
- //true, // drawIt
- false, // drawIt
- false, // hasGrow box
- false, // horizontal scroll?
- true); // vertical scroll?
- if (!this->ListHandleRef())
- {
- // couldn't create a list...
- error = paramErr;
- //ABoxDebug(kABErrBadArgListHandle, error);
- return error;
- } // end if block
-
-
- // set the selection flags which determine how the user
- // can select items in the list
- (*this->ListHandleRef())->selFlags = lOnlyOne | lNoExtend | lNoRect | lNoNilHilite;
-
- // initialize the List's cell's contents with the names of the this->TopicsRef()
- // from the topic list
- //error = GetUsername (userName);
- userName = ::GetString (kABownerNameString);
- ::GetIndString (youFile, kABStrings, kAByourNameHereFile);
-
- // Our list is a one-dimensional object, but since
- // List Mgr lists support rows and columns, i'll contruct
- // the building-loop to support multiple columns even
- // though i'm only concerned with a single column list.
- // This will make it easier in the future if I were
- // to change how the list is displayed.
- //
- index = 1;
- for (cell.v = 0; cell.v < (**this->ListHandleRef()).dataBounds.bottom; ++cell.v)
- {
- for (cell.h = 0; cell.h < (**this->ListHandleRef()).dataBounds.right; ++cell.h)
- {
- topic = (ABTopic *)this->TopicsRef()->NthLink(index);
- if (!topic)
- {
- ++index;
- continue;
- } // end if block
-
- error = topic->GetProperty (kABTopicName, &topicName, NULL);
- error = topic->GetProperty (kABTopicDepth, &topicDepth, NULL);
-
- if (topicName[0] != 0)
- {
- // pad the topic name to simulate indented this->TopicsRef() based
- // upon the "depth" of the topic.
- //
- temp[0] = 0;
- for (i = 0; i < topicDepth; i++)
- ABUString::P2Pstrcat( temp, "\p " );
-
- sameString = ::EqualString (topicName,
- youFile,
- kABcaseSensitive,
- kABdiacriticalSensitive);
- if (sameString && !error)
- {
- // we are now looking at the dummy file "you",
- // so we'll substitute the Sharing Setup control
- // panel's default owner/user name here if possible.
- //
- ::HLock ((Handle)userName);
- ABUString::P2Pstrcat (temp, *userName);
- ::HUnlock ((Handle)userName);
-
- } else {
- ABUString::P2Pstrcat (temp, topicName);
-
- // not the dummy file, so continue...
- } // end if else block
-
- // initialize the cell contents to this string.
- //
- ::LSetCell(&temp[1],
- temp[0],
- cell,
- this->ListHandleRef());
- } // end if block
-
- index++;
-
- } // end of for(cell.h) loop to actually assign the cell values
- } // end of for(cell.v) loop to index the cell values
- ::LDoDraw (true, this->ListHandleRef());
- return error;
-
- } // end of function CreateAndFillTopicList()
-
-
-
-
-
-
- /*=============================== ABox::DrawDialogItem ===============================*/
- //
- // this function will handle the re/drawing of the various custom
- // items in the dialog box
- //
- // from Toolbox Essentials, p. 6-143:
- //
- // Application-Defined Routines
- // If you supply an application-defined item in a dialog box, you must provide a
- // draw procedure for the Dialog Manager to use when displaying the item; that
- // procedure is referred to in this section as MyItem. If you want the Dialog
- // Manager to play sounds other than the system alert sound, you must provide your
- // own sound procedure, referred to in this section as MyAlertSound. To supplement
- // the Dialog Manager’s ability to handle events in the Macintosh multitasking
- // environment, you should provide an event filter function that the Dialog Manager
- // calls whenever it displays alert boxes and modal dialog boxes. This function is
- // referred to as MyEventFilter.
- //
- // MyItem
- // To draw your own application-defined item in a dialog box, provide a draw
- // procedure that takes two parameters: a window pointer to the dialog box and an
- // item number from the dialog box’s item list resource. For example, this is how
- // you should declare the procedure if you were to name it MyItem:
- //
- //
- // PROCEDURE MyItem (theWindow: WindowPtr; itemNo: Integer);
- // theWindow A pointer to the dialog record for the dialog box containing
- // an application-defined item. If your procedure can draw in
- // more than one dialog box, this parameter tells your procedure
- // which one to draw in.
- //
- // itemNo A number corresponding to the position of an item in the item
- // list resource for the specified dialog box. If your procedure
- // draws more than one item, this parameter tells your procedure
- // which one to draw.
- //
- // The Dialog Manager calls your procedure to draw an application-defined item at
- // the time you display the specified dialog box. When calling your draw procedure,
- // the Dialog Manager sets the current port to the dialog box’s graphics port.
- // Normally, you create an invisible dialog box and then use the Window Manager
- // procedure ShowWindow to display the dialog box.
- //
- // Before you display the dialog box, use the SetDialogItem procedure to install
- // this procedure in the dialog record. Before using SetDialogItem, you must first
- // use the GetDialogItem procedure to obtain a handle to an item of type userItem.
- // If you enable the application-defined item that you draw with this procedure,
- // the ModalDialog procedure and the DialogSelect function return the item’s number
- // when the user clicks that item. If your application needs to respond to a user
- // action more complex than this (for example, if your application needs to measure
- // how long the user holds down the mouse or how far the user drags the cursor),
- // your application must track the cursor itself. If you use ModalDialog, your event
- // filter function must handle events inside the item; if you use DialogSelect, your
- // application must handle events inside the item before handing events to DialogSelect.
- //
- //
- // is called by:
- // the dialog manager
- //
- pascal void ABox::DrawDialogItem(DialogPtr dialog, short itemNo)
- {
- short itemType;
- Handle itemHandle;
- Rect itemRect;
-
- OSErr error = noErr;
- ABox *abox;
- ABTopic *topic;
- ListHandle listHandle = NULL;
- Str255 appName;
- Boolean inBackground = false;
- ABoxSplashTimeType splash;
-
- // begin here...
-
- abox = (ABox *)::GetWRefCon(dialog);
- if (!abox)
- return;
-
- error = abox->GetProperty(kABoxCurrentTopic, &topic, NULL);
- if (error)
- return;
-
- error = abox->GetProperty(kABoxInBackground, &inBackground, NULL);
- if (error)
- return;
-
- error = abox->GetProperty(kABoxSplashTimeSeconds, &splash, NULL);
- if (error)
- return;
-
- ::GetDItem(dialog, itemNo, &itemType, &itemHandle, &itemRect);
-
- switch(itemNo)
- {
-
- case kAboutBoxTopic :
-
- // recover the list handle.
- //
- error = abox->GetProperty(kABoxListHandle, &listHandle, NULL);
- if (!error && listHandle)
- {
-
- // draw the list's framing rectangle OUTSIDE the view rectangle.
- // if the frame is drawn inside the view rectangle then these lines
- // will be erased, drawn onto or scrolled by the List Manager since
- // the lines are within the rectangle LM expects to be able to draw in.
- //
- // let the List Manager draw the list
- ::LUpdate (dialog->visRgn, listHandle);
-
- } // end if block
-
- abox->DrawFrame (itemRect);
- break;
-
- case kAboutBoxAppAndVersion:
- abox->DrawFrame(itemRect);
- error = abox->GetProperty(kABoxAppNameAndVersion, &appName, NULL);
- if (!error)
- {
- ::InsetRect(&itemRect, 1, 1);
- error = ABUTextBox::DrawTextBox ((unsigned char *)&(abox->AppNameAndVersionRef()[1]),
- (unsigned long) (abox->AppNameAndVersionRef()[0]),
- &itemRect,
- kNTBJustFull,
- 0,
- NULL,
- NULL);
- }
- break;
-
- case kAboutBoxSlideField:
- if (topic)
- {
- error = topic->Update(dialog);
- } // end if block
- break;
-
- } // end of switch block...
-
- return;
-
- } // end of function DrawDialogItem()
-
-
-
-
-
- /*=============================== ABox::Update ================================*/
- OSErr ABox::Update(WindowPtr /*window*/)
- {
- OSErr error = noErr;
-
- ABTopic *topic;
-
- // begin here...
- //
- if (!this->TopicsRef())
- return error;
-
- topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
- if (topic)
- error = topic->Update(this->GetWindow());
-
- return error;
-
- } // end Update
-
-
-
-
-
-
- /*=============================== ABox::Splash ================================*/
- //
- // return "true" to indicate that the splash is complete and that the abox
- // should be torn down.
- //
- // return "false" to indicate that the splash is not complete, but don't interact
- // with either.
- //
- Boolean ABox::Splash (EventRecord *eventRec)
- {
- Boolean splashDown = false;
- OSErr error = noErr;
- GrafPtr oldPort;
- static long localTimer = 0;
-
- // begin here...
-
- if (this->IsNotSplashScreen())
- return splashDown = false;
-
- if (localTimer == 0)
- localTimer = TickCount();
-
- ::GetPort (&oldPort);
- ::SetPort (this->GetWindow());
-
- if (this->WindowIsntUp())
- {
- ::ShowWindow(this->GetWindow());
- ::SelectWindow(this->GetWindow());
- error = this->CheckAllControls (this->GetWindow(), false);
- this->WindowUpFlagRef() = true;
- } // end if block
-
- error = this->CheckAllControls (this->GetWindow(), false);
- error = this->ChangeControls();
-
- switch (this->SplashTimeRef())
- {
- case kABoxWaitForClickSplash:
- // wait for the user to click or keypress
- // before going away...
- if (eventRec)
- splashDown = ((eventRec->what == keyDown) ||
- (eventRec->what == autoKey) ||
- (eventRec->what == mouseDown));
- localTimer = 0;
- break;
- case kABoxWaitForApplicationSplash:
- // do nothing except sit there...the application will
- // tear us down when it's good and ready...
- splashDown = false;
- localTimer = 0;
- break;
- default:
- // the caller has specified a timed splash screen,
- // so splash we will...
- splashDown = (::TickCount() - localTimer) >= (60 * this->SplashTimeRef());
- break;
- } // end switch block
-
- if (splashDown)
- localTimer = 0;
- ::SetPort (oldPort);
- return splashDown;
- } // end Splash
-
-
-
-
-
- /*=============================== ABox::Event ================================*/
- //
- // ALL INITIAL EVENT HANDLING is focused here...
- //
- // if the abox is modal, then we hand off to a loop of ModalDialog()
- // via the ModalEvent() method.
- //
- // if the abox is modeless, then we determine if the event belongs to
- // the abox dialog, and process accordingly.
- //
- // if the abox is movable modal, then we do that too.
- //
- Boolean ABox::Event(EventRecord *eventRec)
- {
- Boolean handled = false;
- Boolean handledIt = false;
- OSErr error = noErr;
- short itemNo = 0;
- DialogPtr dialog = NULL;
- GrafPtr oldPort;
-
- unsigned long localSleep = 5;
-
- // begin here...
- //
-
- ::GetPort (&oldPort);
- if (this->DoesntHaveWindow() || this->WindowIsntUp())
- return false;
-
- ::SetPort (this->GetWindow());
-
- if (! this->IsModal())
- {
- if (!eventRec)
- return handled = false;
-
- // check the caller's requested splash configuration...
- if (this->Splash(eventRec))
- {
- error = this->Close();
- return true;
- } // end if block
-
- handledIt = CallModalFilterProc(this->ModalUPPRef(), this->GetWindow(), eventRec, &itemNo);
-
- handled = this->HandleEvent(eventRec, itemNo);
- if (itemNo == kAboutBoxOK)
- {
- // sigh. the "OK" button has been clicked. Bye bye...
- error = this->Close();
- handled = true;
- } // end if block
-
- } else {
- // this the stock ModalDialog
-
- do
- {
- ::ModalDialog(this->ModalUPPRef(), &itemNo);
-
- // check the caller's requested splash configuration...
- if (itemNo != kAboutBoxOK) {
- // Take action on the item hit by the user...
- (void)this->HandleEvent (&(this->LastEventRef()), itemNo);
- } // end if block
-
- } while (itemNo != kAboutBoxOK);
-
- this->WindowUpFlagRef() = false;
- error = this->Close();
- handled = true;
- } // end if else block
-
- ::SetPort (oldPort);
-
- return handled;
-
- } // end Event
-
-
-
-
-
- /*=============================== ABox::HandleEvent ================================*/
- //
- // HandleEvent is used to perform the bulk of all event processing for
- // the About Box, whether it is running as a modal dialog, a modeless
- // dialog, or even possibly just as a window.
- //
- // If the abox is processing things via ModalDialog, the itemNo
- // set within the modal dialog filter (ModalDialogEventFilter in our
- // case) and the event are sent directly to here before leaving
- // ModalDialog.
- //
- // If the abox is processing things in a non-modal (a-modal?) fashion,
- // then the Event method has received the event, determined what (if any)
- // item the user has interacted with, and sent the information here
- // for processing.
- //
- Boolean ABox::HandleEvent (EventRecord *event, short itemNo)
- {
- Boolean eventHandled = false;
- OSErr error = noErr;
-
- ABTopic *topic = NULL;
- WindowPtr curWindow = NULL;
- short clickArea;
-
- // begin here...
-
- switch (event->what)
- {
- case mouseDown:
- if (this->IsSplashScreen())
- return eventHandled;
-
- if (! this->IsModal())
- {
- clickArea = ::FindWindow (event->where, &curWindow);
-
- // now process the event...
- switch (clickArea)
- {
- case inDesk:
- case inSysWindow:
- // the click was _outside_ of this application
- // so shove the abox to the background...
- this->ToBackground();
- eventHandled = false;
- break;
- case inDrag:
- if (this->NotOurWindow(curWindow))
- {
- if (this->IsMoveableModal())
- {
- // sorry, can't select a back window (in this app)
- // when a modal type dialog is up.
- ABERR("\psorry, you can't drag another window while moadal.");
- eventHandled = true;
- } else {
- // let the other event loop handler deal with
- // this; we'll just prepare to go to the back
- eventHandled = false;
- this->ToBackground();
- } // end if block
- } else {
- // we are the window being dragged...let the
- // main application loop handle us
- if (this->NotTheFrontWindow())
- // 1.0.4 ty -- checks for bringing to the foreground
- this->ToForeground();
- eventHandled = false;
- } // end if else block
-
- break;
- case inContent:
- // track the event, so to speak...
-
- if (this->NotOurWindow(curWindow))
- {
- if (this->IsMoveableModal())
- {
- // sorry, can't select a back window (in this app)
- // when a modal type dialog is up.
- ABERR("\psorry, you can't select another window's contents while moadal.");
- eventHandled = true;
- } else {
- // let the other event loop handler deal with
- // this; we'll just prepare to go to the back
- eventHandled = false;
- this->ToBackground();
- } // end if block
- } else {
- if (this->NotTheFrontWindow())
- // 1.0.3 ty -- checks for bringing to the foreground
- this->ToForeground();
- error = this->ProcessItemHit (event, itemNo);
- eventHandled = (error) ? false : true;
- } // end if else block
- break;
- default:
- eventHandled = false;
- } // end switch (clickArea)
- } else {
- // a modal dialog also needs to process the events...
- error = this->ProcessItemHit (event, itemNo);
- } // end if block
- break;
-
- case activateEvt:
- // we were either activated or deactivated...
- curWindow = (WindowPtr)(event->message);
- eventHandled = false;
- if (this->NotOurWindow(curWindow))
- {
- if (event->modifiers & activeFlag)
- // some other window is being activated,
- // and this event doesn't belong to us, so
- // move to the background...
- this->ToBackground();
- } else if (!this->IsModal()) {
- if (event->modifiers & activeFlag)
- {
- if (this->NotTheFrontWindow())
- this->ToForeground();
- } else {
- this->ToBackground();
- } // end if else block
-
- } // end if else block
- break;
-
- case osEvt:
- // we're talking major league context switch here gang...
- //
- switch ((event->message >> 24) & 0xFF)
- {
- // Must logical and with 0xFF to get only low byte.
- // High byte of message
- case mouseMovedMessage:
- // big deal, huh?
- break;
- case suspendResumeMessage:
- // layer switch
- if(event->message & resumeFlag)
- {
- // switch into the foreground...
- if (this->IsTheFrontWindow())
- this->ToForeground();
- } else {
- // switch into the background...
- this->ToBackground();
- }
- break;
- } // end switch block
-
- // allow the main event loop to process this
- // event as well by returning false
- eventHandled = false;
- break;
-
- default:
- eventHandled = false;
- break;
-
- } // end switch block
-
- if (this->ReportMemoryFlagRef())
- this->ReportMemory();
-
- return eventHandled;
- } // end HandleEvent()
-
-
-
-
-
- /*=============================== ABox::ToBackground ===============================*/
- OSErr ABox::ToBackground (void)
- {
- OSErr error = noErr;
- ListHandle lh = this->ListHandleRef();
-
- // begin here...
- if (this->IsInForeground())
- {
- this->InBackgroundFlagRef() = true;
- error = this->SaveControlStates (this->GetWindow());
- error = this->CheckAllControls (this->GetWindow(), this->IsInForeground());
-
- // 1.0.7 ty...addition to deactivate the list here
- // when moving to the background.
- //
- if (lh)
- ::LActivate (false, lh);
-
- } // end if block
-
- return error;
- } // end ToBackground
-
-
-
-
- /*=============================== ABox::ToForeground ===============================*/
- OSErr ABox::ToForeground (void)
- {
- OSErr error = noErr;
- ListHandle lh = this->ListHandleRef();
-
- // begin here...
- if (this->IsInBackground())
- {
- this->InBackgroundFlagRef() = false;
- ::SelectWindow(this->GetWindow());
- ::SetPort (this->GetWindow());
- error = this->RestoreControlStates (this->GetWindow());
- // 1.0.7 ty...addition to activate the list here
- // when moving to the background.
- //
- if (lh)
- ::LActivate (true, lh);
-
- } // end if block
-
- return error;
- } // end ToForeground
-
-
-
-
-
-
- /*=============================== ABox::ProcessItemHit ===============================*/
- OSErr ABox::ProcessItemHit (EventRecord *event, short itemNo)
- {
- OSErr error = noErr;
- Point where;
- Cell cell;
- ABTopic *topic;
- Boolean ok = false;
-
- short itemType;
- Handle itemHandle;
- Rect itemRect;
-
- short topicIndex;
- GrafPtr oldPort;
-
- // begin here...
-
- if (!event)
- return paramErr;
-
- if ((event->what != mouseDown) &&
- (event->what != keyDown) &&
- (event->what != autoKey))
- return error;
-
- // get the old port
- ::GetPort (&oldPort);
- ::SetPort (this->GetWindow());
-
- where = event->where;
- ::GlobalToLocal(&where);
-
- ::GetDItem(this->GetWindow(), kAboutBoxSlideField, &itemType, &itemHandle, &itemRect);
-
- switch (itemNo)
- {
- // now check the value of itemNo (if the event hasn't been handled)
- //
- case kAboutBoxAppAndVersion:
- case kAboutBoxSlideField:
- break;
- case kAboutBoxPrevButton:
- case kAboutBoxNextButton:
- if (!this->IsControlActive(GetControlHandle (this->GetWindow(), itemNo)))
- break;
-
- topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
- if (topic)
- {
- if (itemNo == kAboutBoxPrevButton)
- // back up one slide in the current slide list
- // for the current topic
- //
- error = topic->PreviousSlide();
- else
- // advance to the next slide in the current list.
- //
- error = topic->NextSlide();
-
- error = topic->ResizeAndDraw(itemRect, this->GetWindow());
- } // end if block
- break;
-
- case kAboutBoxPlayButton:
- //
- // addition of the play button to replay the
- // controller-less movie or the sound.
- //
- if (!this->IsControlActive(this->GetControlHandle (this->GetWindow(), itemNo)))
- break;
-
- topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
- if (topic)
- {
- // ok, we've got the current topic. Now we'll examine
- // it to see if it is a playable thing, which would
- // be (a) a movie topic without a controller or (b) a
- // sound element of the current slide
- //
-
- Boolean playableMovie = false;
-
- // check to see if the topic _is_ a movie...
- error = topic->GetProperty (kABTopicHasMovieController, &playableMovie, NULL);
- if (!error && !playableMovie)
- {
- // it _is_ a movie without a controller
- // stop the current activity in its tracks
- error = topic->Stop();
- topic->Draw(this->GetWindow());
- } else {
- // ok, it's not a movie...does it have a sound?
-
- ABSlide *cSlide = topic->CurrentSlide();
- if (cSlide)
- {
- // yes, there is a current slide...does it have
- // a sound element?
- //
- ABSound *aSound = (ABSound *)cSlide->GetResourceOfType(kABSoundResource);
-
- if (aSound)
- {
- // stop the current activity in its tracks
- error = aSound->Stop();
- // tell the sound to replay itself...
- aSound->Draw(this->GetWindow());
- } // end if block
- } // end if cSlide;
-
- } // end if block
- } // end if block
- break;
-
- case kAboutBoxTopic:
- // the user clicked in the List
- // if the user has clicked in the topic list then we'll
- // handle the processing here
- //
- // let the List Manager process the mouse down. this includes cell
- // selection dragging, scrolling and double clicks by the user.
-
- // find out where the user clicked...
- if (!this->ListHandleRef())
- break;
-
- topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
- if (topic)
- topicIndex = topic->Ordinal();
- else
- topicIndex = 0;
-
- if (::LClick(where, event->modifiers, this->ListHandleRef()))
- {
- // a double click in a cell has occured.
- // find out in which one of the cells the user has
- // double clicked in.
- cell = ::LLastClick(this->ListHandleRef());
- if (topicIndex && (topicIndex != (cell.v + 1)))
- // not the same topic...
- ok = true;
- else
- ok = false;
- } else {
- // a normal click in the list, so find the cell
- // that was targeted (if any...LGetSelect _can_ return false)...
- ::SetPt (&cell, 0, 0);
- ok = ::LGetSelect (true, &cell, this->ListHandleRef());
- if (ok && (topicIndex == (cell.v + 1)))
- // oops, the user selected the same (current) topic...
- ok = false;
- } // end if block
-
- // if we have this->TopicsRef() in this about box AND the user did indeed
- // select a cell, jump to that topic and display
- //
- if (ok)
- {
- ::LSetSelect (true, cell, this->ListHandleRef());
- topic = (ABTopic *)this->TopicsRef()->GotoLink(cell.v + 1);
- if (topic)
- error = topic->ResizeAndDraw(itemRect, this->GetWindow());
- } else {
- // the user clicked in a blank area of the list, so reset the
- // selection to avoid having a slide showing but no topic highlighted...
- cell.v = topicIndex - 1;
- cell.h = 0;
- ::LSetSelect(true, cell, this->ListHandleRef());
- } // end if (this->TopicsRef()) block
- break;
- case kAboutBoxPreviousTopic:
- case kAboutBoxNextTopic:
- if (itemNo == kAboutBoxPreviousTopic)
- topic = (ABTopic *)this->TopicsRef()->PreviousLink();
- else //if (itemNo == kAboutBoxNextTopic)
- topic = (ABTopic *)this->TopicsRef()->NextLink();
-
- if (topic)
- {
- cell.v = cell.h = 0;
- ok = ::LGetSelect (true, &cell, this->ListHandleRef());
- if (ok)
- // deselect the current List cell
- ::LSetSelect (false, cell, this->ListHandleRef());
- cell.v = topic->Ordinal() - 1;
- cell.h = 0;
- // select the new List cell
- ::LSetSelect(true, cell, this->ListHandleRef());
- ::LAutoScroll(this->ListHandleRef());
-
- error = topic->ResizeAndDraw(itemRect, this->GetWindow());
-
- } // end if else block
- break;
-
- } // end of switch block
-
- error = this->ChangeControls();
-
- // restore the old port
- ::SetPort (oldPort);
-
- return error;
- } // end ProcessItemHit
-
-
-
-
-
- /*=============================== ABox::ModalEventFilter ===============================*/
- //
- // ModalEventFilter always returns a flag, "eventHandled," indicating if the dialog
- // filter box handled the event and that the caller can now examine which item was
- // hit by the user.
- //
- pascal Boolean ABox::ModalEventFilter(DialogPtr dialog, EventRecord *event, short *item)
- {
- // For alert and modal dialog boxes, the Dialog Manager provides a standard event
- // filter function that checks whether the user has pressed the Enter or Return key
- // and, if so, returns the item number of the default button. Your event filter
- // function should always check whether the Return key or Enter key was pressed and,
- // if so, return the item number of the default button in the itemHit parameter and
- // a function result of true. Your event filter function should also check whether
- // the Esc key was pressed and, if so, return the item number for the Cancel button
- // in the itemHit parameter and a function result of true. Your event filter function
- // should also respond to the Command-period key-down event as if the user had clicked
- // the Cancel button.
- //
- Boolean eventHandled = false;
-
- char character;
- Point where;
- Rect itemRect;
- short itemType;
- Handle listItemHandle;
-
- OSErr error = noErr;
-
- ControlHandle controlHandle;
-
- // the ModalFilterProcPtr below becomes a ModalFilterUPP
- ModalFilterUPP modalFilterUPP = NULL;
-
- ABox *abox = NULL;
- ABTopic *currentTopic;
- GrafPtr oldPort;
- WindowPtr aboxWindow;
- Boolean aboxInBackground = false;
- Point pseudoWhere = { 0, 0 };
- ABoxModalIndicator modality = kABoxModal;
- long splash;
-
- // begin here...
-
- if (!(event && item && dialog))
- return false;
-
- abox = (ABox *)::GetWRefCon(dialog);
- if (!abox)
- return false;
-
- // find the window
- error = abox->GetProperty (kABoxWindow, &aboxWindow, NULL);
- if (dialog != aboxWindow || (error != noErr))
- return false;
-
- // find the splashtime...
- error = abox->GetProperty (kABoxSplashTimeSeconds, &splash, NULL);
- if (error != noErr)
- return false;
-
- error = abox->GetProperty (kABoxModalIndicator, &modality, NULL);
- if (error != noErr)
- return false;
-
- ::GetPort (&oldPort);
- ::SetPort (dialog);
-
- where = event->where;
- ::GlobalToLocal(&where);
-
- // do the splash thing?
- if (abox->Splash(event))
- {
- // break outta the loop
- *item = kAboutBoxOK;
- return eventHandled = true;
- } // end if block
-
- // this step here is superfluous if we are a ModalDialog, but
- // is required in this filter if we are a MoveableModal or
- // ModelessDialog to avoid processing the event
- if (::IsDialogEvent (event) && (splash == kABoxNoSplash))
- {
- ::LocalToGlobal(&pseudoWhere);
-
- ::GetDItem(dialog, kAboutBoxTopic, &itemType, &listItemHandle, &itemRect);
-
- if (::PtInRect(where, &itemRect))
- *item = kAboutBoxTopic;
-
-
- // check out some of the mouseDown stuff...if we are modal or
- // moveable modal and the mouseDown is NOT in our window, then
- // we'll have to indicate this to the user. In reality, ModalDialog
- // already does this for us, but there is no system level support
- // for a MoveableModal dialog, so we've gotta simulate the same
- // actions here (with the exception of allowing the menubar to happen)
- if ((event->what == mouseDown) && (modality != kABoxModal))
- {
- // we've gotta manually track the control...
- short controlPart;
- ControlHandle controlHandle = NULL;
-
- eventHandled = false;
- *item = ::FindDItem (dialog, where) + 1;
- controlPart = ::FindControl (where, aboxWindow, &controlHandle);
- if (controlPart == inButton)
- {
- controlPart = ::TrackControl (controlHandle, where, NULL);
- if (controlPart != inButton)
- {
- // forget it...void the event by setting it
- // to something that we'll never be concerned with
- event->what = mouseUp;
- *item = 0;
- } else {
- eventHandled = true;
- } // end if block
- } // end if block
- } // end if block
-
- // Key filtering schemes follow...a standard filter to
- // recognize 'return' as OK and 'ESC' as cancel. What this really means
- // is that [C.K. Haun, Apple Developer Tech Support] never ever want[s] to have to
- // use the mouse to click the cancel buttton ever again, you can just cut and
- // paste this code from now on.
- //
- // do standard filtering for escape and return as OK and Cancel aliases
- // We also invert the button in the dialog, so the user get's visual feedback
- // about the action they just took.
- //
- // Again, if we're using the new calls, then we don't need to do this particular
- // filtering
-
- if ((event->what == keyDown) || (event->what == autoKey))
- {
- character = event->message & charCodeMask;
- switch (character) {
-
- case kReturnKey:
- case kEnterKey:
- case kEscKey:
- *item = kAboutBoxOK;
- // To give visual feedback indicating which item has been selected, you
- // should invert buttons that are activated by keyboard equivalents for
- // all alert and dialog boxes. A good rule of thumb is to invert a button
- // for 8 ticks, long enough to be noticeable but not so long as to be
- // annoying. The Control Manager performs this action whenever a user
- // clicks a button, and your application should do this whenever a user
- // presses the keyboard equivalent of a button click.
- //
- controlHandle = GetControlHandle (aboxWindow, *item);
- eventHandled = FlashControl(controlHandle);
- break;
-
- case kUpArrow:
- case kDownArrow:
- *item = (character == kUpArrow) ? kAboutBoxPreviousTopic : kAboutBoxNextTopic;
- event->where = pseudoWhere;
- event->what = mouseDown;
- event->message = (long)aboxWindow;
- eventHandled = true;
- break;
- case kSpace:
- case kLeftArrow:
- case kRightArrow:
- // the user wants to replay the slide
- // the user wants to see the previous slide.
- // the user wants to see the next slide.
- //
- if (character == kLeftArrow)
- {
- *item = kAboutBoxPrevButton;
- } else if (character == kRightArrow) {
- *item = kAboutBoxNextButton;
- } else if (character == kSpace) {
- *item = kAboutBoxPlayButton;
- } // end if else block
-
- event->where = pseudoWhere;
- event->what = mouseDown;
- event->message = (long)aboxWindow;
- controlHandle = GetControlHandle (aboxWindow, *item);
- eventHandled = FlashControl(controlHandle);
- break;
-
- default:
- break;
- } // end switch(character) block
- } // end if block
-
- } // end if block
-
- if (event->what == updateEvt)
- {
- // By responding to update events for your application’s own inactive windows
- // in this way, you allow ModalDialog to perform a minor switch when necessary
- // so that background applications can update their windows, too.
- //
- GrafPtr tPort;
- UpdateWindowUPP updaterUPP = NULL;
- WindowPtr curWindow = ::FrontWindow();
-
- ::GetPort (&tPort);
- error = abox->GetProperty (kABoxUpdater, &updaterUPP, NULL);
-
- curWindow = ::FrontWindow();
- eventHandled = false;
- while (curWindow)
- {
- //if (abox->IsThisTheWindow(curWindow))
- if (abox->NotOurWindow(curWindow))
- {
- ::SetPort (curWindow);
- if (updaterUPP)
- {
- CallWindowUpdateProc(updaterUPP, curWindow);
- } else {
- // no this->UpdaterRef(), not our update, so toss it
- // to the 4 winds...
- ::BeginUpdate(curWindow);
- ::EndUpdate(curWindow);
- } // end if else block
- ::SetPort (tPort);
- } else {
- // the event IS for us; should we bother to process it, since ModalDialog
- // takes care of these things for us?
- if (modality != kABoxModal)
- {
- ::BeginUpdate(aboxWindow);
- ::UpdtDialog(aboxWindow, (aboxWindow)->visRgn);
- ::EndUpdate(aboxWindow);
- eventHandled = true;
- } // end if block
- } // end if else block
-
- curWindow = (WindowPtr) ((WindowPeek) curWindow)->nextWindow;
- } // end while block
-
- } // end if block
-
- // one final thing if we're under System 7, calling the standard filter.
- // You MUST call the standard filter if you want any of the new dialog things to happen!
- // The OK button border, cursor tracking, and the rest ONLY happen if you call the filter!
- //
- // the ModalFilterProcPtr's below became ModalFilterUPP's
- error = ::GetStdFilterProc(&modalFilterUPP);
- if ((error == noErr) && modalFilterUPP)
- {
- Boolean stdHandled = false;
-
- if (((modality == kABoxModal) && !eventHandled) || (modality != kABoxModal))
- stdHandled = CallModalFilterProc(modalFilterUPP, dialog, event, item);
- } // end if block
-
- // save the event into the ABox object for processing later...
- error = abox->SetProperty (kABoxLastEvent, event, kABoxLastEventSize);
-
- // Allow some of the sub-objects to process the event IF
- // conditions are right...
- if (!abox->Splash(event))
- {
- error = abox->GetProperty (kABoxCurrentTopic, ¤tTopic, NULL);
- if (!error && currentTopic)
- (void)currentTopic->Event(event);
- } // end if block
-
- // give some time to the threads...gotta have threads man!
- error = abox->DoThreads();
-
- // now return to the caller...
- //
- // from Toolbox Essentials, p. 6-136:
- //
- // For events inside the dialog box, ModalDialog passes the event to the event
- // filter function pointed to in the filterProc parameter before handling the
- // event. When the event filter returns false, ModalDialog handles the event. If
- // the event filter function handles the event, the event filter function returns
- // true, and ModalDialog performs no more event handling.
- //
-
- ::SetPort (oldPort);
- return (eventHandled);
-
- } // end of function ModalEventFilter()
-
-
-
-
-
- /*=============================== ABox::ChangeControls ================================*/
- OSErr ABox::ChangeControls(void)
- {
- OSErr error = noErr;
- ABTopic *topic = NULL;
- ABSlide *slide = NULL;
- ABIndex slideNum = 0;
- ABListCount slideCount = 0;
- Boolean playableResources = false;
-
- short itemType;
- Handle playButtonHandle;
- Handle nextButtonHandle;
- Handle prevButtonHandle;
- Rect itemRect;
- Boolean isMovie = false;
- Boolean hasController = false;
- Boolean code = false;
-
- // begin here...
- //
- this->ReportMemory();
-
- if (this->InBackgroundFlagRef())
- return error;
-
- topic = (ABTopic *)(this->TopicsRef()->GetCurrentLink());
- if (!topic)
- return paramErr;
- slide = topic->CurrentSlide();
- if (slide)
- {
- slideNum = slide->Ordinal();
- if (slide->GetResourceOfType (kABSoundResource))
- playableResources = true;
- else
- playableResources = false;
- } // end if block
-
- error = topic->GetProperty (kABTopicNumberOfSlides, &slideCount, NULL);
- error = topic->GetProperty (kABTopicIsMovie, &isMovie, NULL);
- error = topic->GetProperty (kABTopicHasMovieController, &hasController, NULL);
- if (!playableResources && isMovie && !hasController)
- playableResources = true;
-
- ::GetDItem(this->GetWindow(), kAboutBoxPrevButton, &itemType, &prevButtonHandle, &itemRect);
- ::GetDItem(this->GetWindow(), kAboutBoxNextButton, &itemType, &nextButtonHandle, &itemRect);
- ::GetDItem(this->GetWindow(), kAboutBoxPlayButton, &itemType, &playButtonHandle, &itemRect);
-
- code = (slideNum > 1) && !isMovie && (this->SplashTimeRef() == kABoxNoSplash);
- error = this->CheckControl((ControlHandle)prevButtonHandle, code);
-
- code = (slideNum < slideCount) && !isMovie && (this->SplashTimeRef() == kABoxNoSplash);
- error = this->CheckControl((ControlHandle)nextButtonHandle, code);
-
- code = playableResources && (this->SplashTimeRef() == kABoxNoSplash);
- error = this->CheckControl((ControlHandle)playButtonHandle, code);
-
- return error;
-
- } // end ChangeControls
-
-
-
-
-
- /*=============================== ABox::ReportMemory ================================*/
- void ABox::ReportMemory(void)
- {
- long freeMemNumber;
- Str255 freeMemString;
-
- GrafPtr oldPort;
- Rect rect;
-
- // begin here...
- //
- if (!this->ReportMemoryFlagRef())
- return;
-
- ::GetPort (&oldPort);
- ::SetPort (this->GetWindow());
-
- freeMemNumber = ::FreeMem();
- ::NumToString (freeMemNumber, freeMemString);
- rect.left = (this->GetWindow())->portRect.left;
- rect.bottom = (this->GetWindow())->portRect.bottom;
- rect.right = rect.left + ::StringWidth(freeMemString) * 1.20;
- rect.top = rect.bottom - kABscrollBarWidth;
- ::EraseRect (&rect);
- ::MoveTo (rect.left, rect.bottom);
- ::DrawString (freeMemString);
- ::SetPort (oldPort);
-
- return;
- } // end ReportMemory
-
-
-
-
-
- /*=============================== ABox::Stop ================================*/
- OSErr ABox::Stop(void)
- {
- OSErr error = noErr;
- ABTopic *topic;
-
- // begin here...
- //
- if (this->TopicsRef())
- {
- topic = (ABTopic *)(this->TopicsRef()->GetCurrentLink());
- if (topic)
- error = topic->Stop();
- } // end if (slides) block
-
- return error;
-
- } // end Stop
-
-
-
-
-
-
- // end of file